package com.async.handler.impl;

import com.async.config.SpringBeanConfig;
import com.async.domain.entity.AsyncReq;
import com.async.enums.AsyncTypeEnum;
import com.async.enums.ExecStatusEnum;
import com.async.handler.context.AsyncStrategyContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import java.util.Collections;
import java.util.List;
import java.util.Objects;

@Slf4j
@Component
public class SyncSaveHandlerService extends AbstractAsyncHandlerService{
    @Override
    public boolean execute(AsyncStrategyContext context) {
        // 同步处理，由于不能影响主线程事务，但是异步方法上面又有事务所有需要开启新事物
        TransactionStatus status = null;
        PlatformTransactionManager transactionManager = null;
        if (TransactionSynchronizationManager.isActualTransactionActive()) {
            DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
            definition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
            transactionManager = SpringBeanConfig.getBean(PlatformTransactionManager.class);
            status = transactionManager.getTransaction(definition);
        }
        try {
            context.getJoinPoint().proceed();
            // 提交事务
            if (Objects.nonNull(status)){
                transactionManager.commit(status);
            }
        } catch (Throwable e) {
            // 处理失败保存到数据库
            log.warn("同步保存失败:{}",context.getAsyncExecDto(),e);
            AsyncReq asyncReq = this.saveAsyncReq(context.getAsyncExecDto(), ExecStatusEnum.ERROR.getStatus());
            // 保存失败异步消息处理
            if (Objects.isNull(asyncReq)){
                asyncProducer.send(context.getAsyncExecDto());
            }
        }
        return true;
    }

    @Override
    public List<String> listType() {
        return Collections.singletonList(AsyncTypeEnum.SYNC_SAVE.name());
    }
}
